package cn.itcast.shop.order.action;

import java.io.IOException;
import java.text.ParseException;
import java.util.Date;
import java.util.Properties;
import java.util.Set;

import javax.servlet.ServletException;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import javax.servlet.http.HttpSession;

import org.apache.struts2.ServletActionContext;
import org.springframework.beans.factory.annotation.Autowired;

import com.opensymphony.xwork2.ActionSupport;
import com.opensymphony.xwork2.ModelDriven;

import cn.itcast.shop.cart.service.CartService;
import cn.itcast.shop.order.domain.OrderItem;
import cn.itcast.shop.order.domain.Orders;
import cn.itcast.shop.order.exception.OrderException;
import cn.itcast.shop.order.service.OrderService;
import cn.itcast.shop.user.domain.User;
import cn.itcast.shop.utils.pagebean.PageBean;

/**
 * 订单模块Action
 */
public class OrderAction extends ActionSupport implements ModelDriven<Orders> {

	private static final long serialVersionUID = 3671653099233758391L;

	/**
	 * 注入订单业务对象
	 */
	@Autowired
	private OrderService orderService;

	/**
	 * 注入购物车业务对象
	 */
	@Autowired
	private CartService cartService;
	
	/**
	 * 模型驱动对象
	 */
	private Orders orders = new Orders();
	
	/**
	 * 购物车条目ID
	 */
	private String cartItemIds;
	
	/**
	 * 页码
	 */
	private int page;

	/**
	 * 分页对象
	 */
	private PageBean<Orders> pageBean;

	public PageBean<Orders> getPageBean() {
		return pageBean;
	}

	/**
	 * Struts2框架会自动把请求中的page属性赋值
	 */
	public void setPage(int page) {
		this.page = page;
	}

	/**
	 * Struts2框架会自动把请求中的cartItemIds属性赋值
	 */
	public void setCartItemIds(String cartItemIds) {
		this.cartItemIds = cartItemIds;
	}

	@Override
	public Orders getModel() {
		return orders;
	}

	private String getUrl() {
		// 等于 /项目名/Servlet路径?method=find&pc=3
		HttpServletRequest req = ServletActionContext.getRequest();
		String url = req.getRequestURI() + "?" + req.getQueryString();
		int index = url.lastIndexOf("&page=");
		if (index != -1) {
			url = url.substring(0, index);
		}
		return url;
	}

	/**
	 * 创建订单
	 */
	public String createOrder() throws IOException {
		Set<OrderItem> setOrderItem;
		try {
			//调用业务层方法通过购物车条目ID，去组装订单项
			setOrderItem = orderService.loadOrderItem(cartItemIds);
		} catch (OrderException e) {
			HttpServletResponse resp = ServletActionContext.getResponse();
			//组装页面弹窗代码
			resp.setContentType("text/html;charset=UTF-8");
			String message = "<script>alert('" + e.getMessage()
					+ "');location.href='${pageContext.request.contextPath}/cart_findByUid.action;'</script>";
			resp.getWriter().println(message);
			return NONE;
		}
		//创建订单条目失败
		if (setOrderItem.size() == 0) {
			HttpServletRequest req = ServletActionContext.getRequest();
			req.setAttribute("code", "error");
			req.setAttribute("msg", "状态异常，创建订单失败！");
			return "msg";
		}
		//给订单设值
		orders.setSetOrderItem(setOrderItem);
		//设值订单创建时间
		orders.setOrdertime(new Date());
		//设置订单状态 1 为未付款
		orders.setState(1);
		User user = (User) ServletActionContext.getRequest().getSession().getAttribute("sessionUser");
		//给订单设置所属用户
		orders.setUser(user);
		//创建订单
		orders = orderService.createOrder(orders);
		//订单创建完成后把购物车的商品清除
		cartService.clearCart(user.getUid());
		return "ordersuccPage";
	}

	/**
	 * 查询我的订单
	 */
	public String myOrder() {
		User user = (User) ServletActionContext.getRequest().getSession().getAttribute("sessionUser");
		//通过用户ID查询所有订单
		pageBean = orderService.findByUid(user.getUid(), page);
		//给分页对象设置Url链接值
		pageBean.setUrl(getUrl());
		return "orderListPage";
	}

	/**
	 * 查询当月账单
	 * @throws ParseException 
	 */
	public String getMonthZD() throws ParseException {
		HttpServletRequest request = ServletActionContext.getRequest();
		HttpSession session = request.getSession();
		User user = (User) session.getAttribute("sessionUser");
		String zddate = request.getParameter("zddate");
		double totalMoney = 0;
		if(zddate==null||zddate==""){
			pageBean = orderService.findByUid(user.getUid(), page);
		}else{
			pageBean = orderService.findThisMonthZD(user.getUid(),page , zddate);
			if(pageBean.getList()!=null){
				for (Orders orders : pageBean.getList()) {
					if(orders.getState()>1 && orders.getState()<5)
					totalMoney += orders.getTotal();
				}
			}
			request.setAttribute("year", zddate.substring(0,4));
			request.setAttribute("month", zddate.substring(5,7));
		}
		request.setAttribute("totalMoney", totalMoney);
		pageBean.setUrl(getUrl());
		return "orderListPage";
	}
	
	/**
	 * 查询订单详细信息
	 * 
	 * @return
	 */
	public String findByOid() {
		orders = orderService.findByOid(orders.getOid());
		return "orderdescPage";
	}

	/**
	 * 支付订单
	 * 
	 * @return
	 */
	public String payOrder() {
		orders = orderService.findByOid(orders.getOid());
		return "payPage";
	}

	/**
	 * 取消订单
	 */
	public String cancelOrder() {
		//首先查询出要取消的订单
		orders = orderService.findByOid(orders.getOid());
		//如果订单状态不是1 ，既未支付状态
		if (orders.getState() != 1) {
			HttpServletRequest req = ServletActionContext.getRequest();
			req.setAttribute("code", "error");
			req.setAttribute("msg", "状态异常，取消订单失败！");
			return "msg";
		} else {
			//设置订单状态为5，已取消
			orderService.updateState(orders.getOid(), 5);
			HttpServletRequest req = ServletActionContext.getRequest();
			req.setAttribute("code", "success");
			req.setAttribute("msg", "您的订单已取消！");
			return "msg";
		}
	}

	/**
	 * 确认收货
	 */
	public String confirmOrder() {
		orders = orderService.findByOid(orders.getOid());
		//只有订单状态为已发货才能确认收货
		if (orders.getState() != 3) {
			HttpServletRequest req = ServletActionContext.getRequest();
			req.setAttribute("code", "error");
			req.setAttribute("msg", "状态异常，收货失败！");
			return "msg";
		} else {
			orderService.updateState(orders.getOid(), 4);
			HttpServletRequest req = ServletActionContext.getRequest();
			req.setAttribute("code", "success");
			req.setAttribute("msg", "收货成功，您的订单已收货！");
			return "msg";
		}
	}

	/**
	 * 调用易宝支付接口
	 * 
	 * @param req
	 * @param resp
	 * @return
	 * @throws ServletException
	 * @throws IOException
	 */
	public String payment() throws IOException {
		HttpServletRequest req = ServletActionContext.getRequest();
		Properties props = new Properties();
		//加载易宝支付的配置文件，账号，秘钥
		props.load(this.getClass().getClassLoader().getResourceAsStream("payment.properties"));
		/*
		 * 1. 准备13个参数
		 */
		String p0_Cmd = "Buy";// 业务类型，固定值Buy
		String p1_MerId = props.getProperty("p1_MerId");// 商号编码，在易宝的唯一标识
		String p2_Order = orders.getOid();// 订单编码
		String p3_Amt = "0.01";// 支付金额
		String p4_Cur = "CNY";// 交易币种，固定值CNY
		String p5_Pid = "";// 商品名称
		String p6_Pcat = "";// 商品种类
		String p7_Pdesc = "";// 商品描述
		String p8_Url = props.getProperty("p8_Url");// 在支付成功后，易宝会访问这个地址。
		String p9_SAF = "";// 送货地址
		String pa_MP = "";// 扩展信息
		String pd_FrpId = req.getParameter("yh");// 支付通道
		String pr_NeedResponse = "1";// 应答机制，固定值1

		/*
		 * 2. 计算hmac 需要13个参数 需要keyValue 需要加密算法
		 */
		String keyValue = props.getProperty("keyValue");
		//使用易宝支付提供的方法生成加密后的密码
		String hmac = PaymentUtil.buildHmac(p0_Cmd, p1_MerId, p2_Order, p3_Amt, p4_Cur, p5_Pid, p6_Pcat, p7_Pdesc,
				p8_Url, p9_SAF, pa_MP, pd_FrpId, pr_NeedResponse, keyValue);
		
		/*
		 * 3. 重定向到易宝的支付网关
		 */
		StringBuilder sb = new StringBuilder("https://www.yeepay.com/app-merchant-proxy/node");
		sb.append("?").append("p0_Cmd=").append(p0_Cmd);
		sb.append("&").append("p1_MerId=").append(p1_MerId);
		sb.append("&").append("p2_Order=").append(p2_Order);
		sb.append("&").append("p3_Amt=").append(p3_Amt);
		sb.append("&").append("p4_Cur=").append(p4_Cur);
		sb.append("&").append("p5_Pid=").append(p5_Pid);
		sb.append("&").append("p6_Pcat=").append(p6_Pcat);
		sb.append("&").append("p7_Pdesc=").append(p7_Pdesc);
		sb.append("&").append("p8_Url=").append(p8_Url);
		sb.append("&").append("p9_SAF=").append(p9_SAF);
		sb.append("&").append("pa_MP=").append(pa_MP);
		sb.append("&").append("pd_FrpId=").append(pd_FrpId);
		sb.append("&").append("pr_NeedResponse=").append(pr_NeedResponse);
		sb.append("&").append("hmac=").append(hmac);

		//调用方法，将请求重定向到易宝支付网关
		ServletActionContext.getResponse().sendRedirect(sb.toString());
		return NONE;

	}

	/**
	 * 回馈方法 当支付成功时，易宝会访问这里 用两种方法访问： 
	 * 1.引导用户的浏览器重定向(如果用户关闭了浏览器，就不能访问这里了)
	 * 2.易宝的服务器会使用点对点通讯的方法访问这个方法。（必须回馈success，不然易宝服务器会一直调用这个方法）
	 * 
	 * @param req
	 * @param resp
	 * @return
	 * @throws ServletException
	 * @throws IOException
	 */
	public String back() throws IOException {
		HttpServletRequest req = ServletActionContext.getRequest();
		HttpServletResponse resp = ServletActionContext.getResponse();
		/*
		 * 1. 获取12个参数
		 */
		String p1_MerId = req.getParameter("p1_MerId");
		String r0_Cmd = req.getParameter("r0_Cmd");
		String r1_Code = req.getParameter("r1_Code");
		String r2_TrxId = req.getParameter("r2_TrxId");
		String r3_Amt = req.getParameter("r3_Amt");
		String r4_Cur = req.getParameter("r4_Cur");
		String r5_Pid = req.getParameter("r5_Pid");
		String r6_Order = req.getParameter("r6_Order");
		String r7_Uid = req.getParameter("r7_Uid");
		String r8_MP = req.getParameter("r8_MP");
		String r9_BType = req.getParameter("r9_BType");// 交易结果返回方式
		String hmac = req.getParameter("hmac");
		/*
		 * 2. 获取keyValue
		 */
		Properties props = new Properties();
		props.load(this.getClass().getClassLoader().getResourceAsStream("payment.properties"));
		String keyValue = props.getProperty("keyValue");
		/*
		 * 3. 调用PaymentUtil的校验方法来校验调用者的身份 >如果校验失败：保存错误信息，转发到msg.jsp >如果校验通过： *
		 * 判断访问的方法是重定向还是点对点，如果要是重定向 修改订单状态，保存成功信息，转发到msg.jsp *
		 * 如果是点对点：修改订单状态，返回success
		 */
		boolean bool = PaymentUtil.verifyCallback(hmac, p1_MerId, r0_Cmd, r1_Code, r2_TrxId, r3_Amt, r4_Cur, r5_Pid,
				r6_Order, r7_Uid, r8_MP, r9_BType, keyValue);
		if (!bool) {
			req.setAttribute("code", "error");
			req.setAttribute("msg", "无效的签名，支付失败！（你不是好人）");
			return "msg";
		}
		if (r1_Code.equals("1")) { // 表示支付结果成功
			if (r9_BType.equals("1")) {
				orders = orderService.findByOid(r6_Order);
				int status = orders.getState();
				if (status == 1) {
					orderService.updateState(r6_Order, 2);
					req.setAttribute("msg", "支付成功");
					req.setAttribute("code", "success");
					return "msg";
				} else {
					req.setAttribute("msg", "状态异常，支付失败！");
					req.setAttribute("code", "error");
					return "msg";
				}
			} 
			else if (r9_BType.equals("2")) {
				resp.getWriter().print("success");
				return NONE;
			}
		} else {
			req.setAttribute("msg", "状态异常，支付失败！");
			req.setAttribute("code", "error");
			return "msg";
		}
		return NONE;
	}

}
